///*
// * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
// * <p>
// * Licensed under the Apache License, Version 2.0 (the "License"); you may not
// * use this file except in compliance with the License. You may obtain a copy of
// * the License at
// * <p>
// * https://www.apache.org/licenses/LICENSE-2.0
// * <p>
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// * License for the specific language governing permissions and limitations under
// * the License.
// */
//package com.ctrip.corp.obt.shard.sql.parser.tenant;
//
//
//import com.ctrip.corp.obt.generic.utils.CollectionUtils;
//import com.ctrip.corp.obt.generic.utils.ExceptionUtils;
//import com.ctrip.corp.obt.generic.utils.StringPool;
//import com.ctrip.corp.obt.shard.sql.parser.AbstractSqlParser;
//import lombok.Data;
//import lombok.EqualsAndHashCode;
//import lombok.experimental.Accessors;
//import lombok.extern.slf4j.Slf4j;
//import net.sf.jsqlparser.expression.BinaryExpression;
//import net.sf.jsqlparser.expression.Expression;
//import net.sf.jsqlparser.expression.Parenthesis;
//import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
//import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
//import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
//import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
//import net.sf.jsqlparser.expression.operators.relational.InExpression;
//import net.sf.jsqlparser.expression.operators.relational.ItemsList;
//import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
//import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax;
//import net.sf.jsqlparser.schema.Column;
//import net.sf.jsqlparser.schema.Table;
//import net.sf.jsqlparser.statement.delete.Delete;
//import net.sf.jsqlparser.statement.insert.Insert;
//import net.sf.jsqlparser.statement.select.FromItem;
//import net.sf.jsqlparser.statement.select.Join;
//import net.sf.jsqlparser.statement.select.LateralSubSelect;
//import net.sf.jsqlparser.statement.select.PlainSelect;
//import net.sf.jsqlparser.statement.select.SelectExpressionItem;
//import net.sf.jsqlparser.statement.select.SubJoin;
//import net.sf.jsqlparser.statement.select.SubSelect;
//import net.sf.jsqlparser.statement.select.ValuesList;
//import net.sf.jsqlparser.statement.update.Update;
//
//import java.util.List;
//
//
///**
// * 租户 SQL 解析器（ TenantId 行级 ）
// *
// * @author marco.zheng
// * @since 2022-02-10
// */
//@Data
//@Slf4j
//@Accessors(chain = true)
//@EqualsAndHashCode(callSuper = true)
//public class TenantSqlParser extends AbstractSqlParser {
//
//    private TenantHandler tenantHandler;
//
//    /**
//     * insert 语句处理
//     */
//    @Override
//    public void processInsert(Insert insert) {
//        if (tenantHandler.ignoreTable(insert.getTable().getName())) {
//            // 过滤退出执行
//            return;
//        }
//        insert.getColumns().add(new Column(tenantHandler.getTenantIdColumn()));
//        if (insert.getSelect() != null) {
//            processPlainSelect((PlainSelect) insert.getSelect().getSelectBody(), true);
//        } else if (insert.getItemsList() != null) {
//            ItemsList itemsList = insert.getItemsList();
//            if (itemsList instanceof MultiExpressionList) {
//                ((MultiExpressionList) itemsList).getExpressionLists().forEach(el -> el.getExpressions().add(tenantHandler.getTenantId()));
//            } else {
//                ((ExpressionList) insert.getItemsList()).getExpressions().add(tenantHandler.getTenantId());
//            }
//        } else {
//            throw ExceptionUtils.mpe("Failed to process multiple-table update, please exclude the tableName or statementId");
//        }
//    }
//
//
//    /**
//     * update 语句处理
//     */
//    @Override
//    public void processUpdate(Update update) {
//        Table table = update.getTable();
//        String name = table.getName();
//        if (tenantHandler.ignoreTable(name)) {
//            // 过滤退出执行
//            return;
//        }
//        update.setWhere(this.andExpression(table, update.getWhere()));
//    }
//
//    /**
//     * delete 语句处理
//     */
//    @Override
//    public void processDelete(Delete delete) {
//        Table table = delete.getTable();
//        String name = table.getName();
//        if (tenantHandler.ignoreTable(name)) {
//            // 过滤退出执行
//            return;
//        }
//        delete.setWhere(this.andExpression(table, delete.getWhere()));
//    }
//
//    /**
//     * delete update 语句 where 处理
//     */
//    private BinaryExpression andExpression(Table table, Expression where) {
//        //获得where条件表达式
//        EqualsTo equalsTo = new EqualsTo();
//        equalsTo.setLeftExpression(this.getAliasColumn(table));
//        equalsTo.setRightExpression(tenantHandler.getTenantId());
//        if (null != where) {
//            if (where instanceof OrExpression) {
//                return new AndExpression(equalsTo, new Parenthesis(where));
//            } else {
//                return new AndExpression(equalsTo, where);
//            }
//        }
//        return equalsTo;
//    }
//
//    /**
//     * 处理 PlainSelect
//     */
//    @Override
//    public void processPlainSelect(PlainSelect plainSelect) {
//        processPlainSelect(plainSelect, false);
//    }
//
//
//    /**
//     * 处理 PlainSelect
//     *
//     * @param plainSelect ignore
//     * @param addColumn   是否添加租户列,insert into select语句中需要
//     */
//    private void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
//        FromItem fromItem = plainSelect.getFromItem();
//        if (fromItem instanceof Table) {
//            Table fromTable = (Table) fromItem;
//            if (!this.getTenantHandler().ignoreTable(fromTable.getName())) {
//                plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable));
//                if (addColumn) {
//                    plainSelect.getSelectItems().add(new SelectExpressionItem(
//                        new Column(this.getTenantHandler().getTenantIdColumn())));
//                }
//            }
//        } else {
//            processFromItem(fromItem);
//        }
//        List<Join> joins = plainSelect.getJoins();
//        if (CollectionUtils.isNotEmpty(joins)) {
//            joins.forEach(j -> {
//                processJoin(j);
//                processFromItem(j.getRightItem());
//            });
//        }
//    }
//
//    /**
//     * 处理子查询等
//     */
//    private void processFromItem(FromItem fromItem) {
//        if (fromItem instanceof SubJoin) {
//            SubJoin subJoin = (SubJoin) fromItem;
//            if (subJoin.getJoinList() != null) {
//                subJoin.getJoinList().forEach(this::processJoin);
//            }
//            if (subJoin.getLeft() != null) {
//                processFromItem(subJoin.getLeft());
//            }
//        } else if (fromItem instanceof SubSelect) {
//            SubSelect subSelect = (SubSelect) fromItem;
//            if (subSelect.getSelectBody() != null) {
//                processSelectBody(subSelect.getSelectBody());
//            }
//        } else if (fromItem instanceof ValuesList) {
//            log.debug("Perform a subquery, if you do not give us feedback");
//        } else if (fromItem instanceof LateralSubSelect) {
//            LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
//            if (lateralSubSelect.getSubSelect() != null) {
//                SubSelect subSelect = lateralSubSelect.getSubSelect();
//                if (subSelect.getSelectBody() != null) {
//                    processSelectBody(subSelect.getSelectBody());
//                }
//            }
//        }
//    }
//
//    /**
//     * 处理联接语句
//     */
//    private void processJoin(Join join) {
//        if (join.getRightItem() instanceof Table) {
//            Table fromTable = (Table) join.getRightItem();
//            if (this.tenantHandler.ignoreTable(fromTable.getName())) {
//                // 过滤退出执行
//                return;
//            }
//            join.setOnExpression(builderExpression(join.getOnExpression(), fromTable));
//        }
//    }
//
//    /**
//     * 处理条件:
//     * 支持 getTenantHandler().getTenantId()是一个完整的表达式：tenant in (1,2)
//     * 默认tenantId的表达式： LongValue(1)这种依旧支持
//     */
//    private Expression builderExpression(Expression currentExpression, Table table) {
//        final Expression tenantExpression = this.getTenantHandler().getTenantId();
//        Expression appendExpression;
//        if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) {
//            appendExpression = new EqualsTo();
//            ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table));
//            ((EqualsTo) appendExpression).setRightExpression(tenantExpression);
//        } else {
//            appendExpression = processTableAlias4CustomizedTenantIdExpression(tenantExpression, table);
//        }
//        if (currentExpression == null) {
//            return appendExpression;
//        }
//        if (currentExpression instanceof BinaryExpression) {
//            BinaryExpression binaryExpression = (BinaryExpression) currentExpression;
//            if (binaryExpression.getLeftExpression() instanceof FromItem) {
//                processFromItem((FromItem) binaryExpression.getLeftExpression());
//            }
//            if (binaryExpression.getRightExpression() instanceof FromItem) {
//                processFromItem((FromItem) binaryExpression.getRightExpression());
//            }
//        } else if (currentExpression instanceof InExpression) {
//            InExpression inExp = (InExpression) currentExpression;
//            ItemsList rightItems = inExp.getRightItemsList();
//            if (rightItems instanceof SubSelect) {
//                processSelectBody(((SubSelect) rightItems).getSelectBody());
//            }
//        }
//        if (currentExpression instanceof OrExpression) {
//            return new AndExpression(new Parenthesis(currentExpression), appendExpression);
//        } else {
//            return new AndExpression(currentExpression, appendExpression);
//        }
//    }
//
//    /**
//     * 目前: 针对自定义的tenantId的条件表达式[tenant_id in (1,2,3)]，无法处理多租户的字段加上表别名
//     * select a.id, b.name
//     * from a
//     * join b on b.aid = a.id and [b.]tenant_id in (1,2) --别名[b.]无法加上 TODO
//     *
//     * @param expression
//     * @param table
//     * @return 加上别名的多租户字段表达式
//     */
//    private Expression processTableAlias4CustomizedTenantIdExpression(Expression expression, Table table) {
//        //cannot add table alias for customized tenantId expression,
//        // when tables including tenantId at the join table position
//        return expression;
//    }
//
//    /**
//     * 租户字段别名设置
//     * <p>tableName.tenantId 或 tableAlias.tenantId</p>
//     *
//     * @param table 表对象
//     * @return 字段
//     */
//    private Column getAliasColumn(Table table) {
//        StringBuilder column = new StringBuilder();
//        if (null == table.getAlias()) {
//            column.append(table.getName());
//        } else {
//            column.append(table.getAlias().getName());
//        }
//        column.append(StringPool.DOT);
//        column.append(tenantHandler.getTenantIdColumn());
//        return new Column(column.toString());
//    }
//}
